From afe837d7e619a4590399be681fe8d32d36c68da2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Nov 2015 13:11:19 -0800 Subject: [PATCH] Add more safeguards around odd filenames This commit is targeted at fixing #2102 via two routes: 1. The dependency on `tar` was upgraded to include more contextual information in error messages about why the unpack failed. This should help diagnose these sorts of issues that happen in the first place. 2. Packaging crates that have files with odd filenames is no longer allowed. An error is returned indicating that the files cannot be packaged as they're not cross platform. The currently rejected set of files are non-utf8 filenames (already present) and those containing characters special on Windows. Closes #2102 --- Cargo.lock | 12 +++++++++--- src/cargo/ops/cargo_package.rs | 28 ++++++++++++++++++++++++++++ tests/test_cargo_package.rs | 24 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0e49fbfd..2c46314bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ dependencies = [ "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -200,6 +200,11 @@ name = "libc" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libgit2-sys" version = "0.3.6" @@ -356,11 +361,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "tar" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index e08281814..635aaf5c3 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -155,6 +155,7 @@ fn tar(pkg: &Package, src: &PathSource, config: &Config, for file in try!(src.list_files(pkg)).iter() { if &**file == dst { continue } let relative = util::without_prefix(&file, &root).unwrap(); + try!(check_filename(relative)); let relative = try!(relative.to_str().chain_error(|| { human(format!("non-utf8 path in source directory: {}", relative.display())) @@ -224,3 +225,30 @@ fn run_verify(config: &Config, pkg: &Package, tar: &Path) Ok(()) } + +// It can often be the case that files of a particular name on one platform +// can't actually be created on another platform. For example files with colons +// in the name are allowed on Unix but not on Windows. +// +// To help out in situations like this, issue about weird filenames when +// packaging as a "heads up" that something may not work on other platforms. +fn check_filename(file: &Path) -> CargoResult<()> { + let name = match file.file_name() { + Some(name) => name, + None => return Ok(()), + }; + let name = match name.to_str() { + Some(name) => name, + None => { + return Err(human(format!("path does not have a unicode filename \ + which may not unpack on all platforms: {}", + file.display()))) + } + }; + let bad_chars = ['/', '\\', '<', '>', ':', '"', '|', '?', '*']; + for c in bad_chars.iter().filter(|c| name.contains(**c)) { + return Err(human(format!("cannot package a filename with a special \ + character `{}`: {}", c, file.display()))) + } + Ok(()) +} diff --git a/tests/test_cargo_package.rs b/tests/test_cargo_package.rs index 6e59a3647..5088d1ce2 100644 --- a/tests/test_cargo_package.rs +++ b/tests/test_cargo_package.rs @@ -427,3 +427,27 @@ src[..]main.rs "unexpected filename: {:?}", f.header().path()) } }); + +#[cfg(unix)] // windows doesn't allow these characters in filenames +test!(package_weird_characters { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + "#) + .file("src/main.rs", r#" + fn main() { println!("hello"); } + "#) + .file("src/:foo", ""); + + assert_that(p.cargo_process("package"), + execs().with_status(101).with_stderr("\ +warning: [..] +failed to prepare local package for uploading + +Caused by: + cannot package a filename with a special character `:`: src/:foo +")); +}); -- 2.30.2